package com.zz.framework.core.base

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.zz.framework.core.ext.*
import com.zz.framework.core.utils.IntentBuilder
import com.zz.framework.core.view.BaseUIFactory
import com.zz.framework.core.view.BaseUIProvider
import com.zz.framework.core.view.SimpleBaseUIFactory
import com.zz.framework.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe

/**
 * Copyright © 2019 zanezhao All rights reserved.
 * Created by zanezhao on 2019-11-13 15:40.
 *
 * @author: zanezhao 1820022519@qq.com
 * @version: V1.0
 */
open abstract class BaseUIFragment : Fragment(), CoroutineScope by MainScope() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mBaseAttribute = BaseAttribute()
        onInitAttribute(mBaseAttribute)
        var view: View? = null
        if (initContentView() > 0) {
            if (mBaseAttribute.mHasTitle) {
                container?.let {
                    view = it.inflate(R.layout.activity_with_toolbar_layout, false)
                    var mContentLayout = view?.findViewById<FrameLayout>(R.id.mContentLayout)
                    var contentView = inflate(initContentView(), null, false);
                    mContentLayout?.addView(contentView)
                }
            } else {
                view = inflater.inflate(initContentView(), container, false)
            }
        } else {
            throw Throwable("layout must set")
        }
        return view
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        initContentAttribute(view)
        initView(view)
        initData()
        super.onViewCreated(view, savedInstanceState)
        EventBus.getDefault().register(this)
    }


    open fun getLayoutResId(): Int {
        return mBaseAttribute.mContentLayoutId
    }

    open fun initView(view: View) {

    }

    open fun initData() {

    }

    protected fun updateTitle(title: String?) {
        mTextViewTitle?.setText(title ?: "")
    }

    @Subscribe
    open fun onMessageEvent(e: Byte) {

    }

    override fun onDestroyView() {
        super.onDestroyView()
        EventBus.getDefault().unregister(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }

    public fun getIntent(): Intent {
        return requireActivity().intent
    }

    private fun initContentAttribute(view: View) {
        if (mBaseAttribute.mHasTitle) {
            initBaseUIFactory()
            mRelativeLayoutTitle = view.findViewById(mBaseAttribute.mTitleLayoutId)
            if (mBaseAttribute.mTitleLayoutBgColorRes > 0) {
                mRelativeLayoutTitle?.setBackgroundColor(resources.getColor(mBaseAttribute.mTitleLayoutBgColorRes))
            }
            if (mBaseAttribute.mAddBackButton) {
                mButtonBack = onCreateBackButton()
                if (mButtonBack != null) {
                    mButtonBack?.onClick(block = {
                        getBaseActivity()?.onBackPressed()
                    })
                    mRelativeLayoutTitle?.addView(mButtonBack, onCreateBackButtonLayoutParams())
                }
            }
            if (mBaseAttribute.mAddTitleText) {
                if (mBaseAttribute.mTitleText == null) {
                    addTextInTitle(mBaseAttribute.mTitleTextStringId)
                } else {
                    addTextInTitle(mBaseAttribute.mTitleText!!)
                }
            }
            mBaseUIFactory?.onTitleCreated(requireActivity(), mButtonBack, mTextViewTitle!!)
            mBaseUIFactory?.let {
                it.titleBackagegroundColorRes?.let {
                    if (it > 0) {
                        mRelativeLayoutTitle?.setBackgroundColor(resources.getColor(it))
                    }
                }
                it.titleBackagegroundDrawbleRes?.let {
                    if (it > 0) {
                        mRelativeLayoutTitle?.setBackgroundResource(it)
                    }
                }
            }
        } else {
            if (mBaseAttribute.mTitleLayoutId != 0) {
                val v: View? = view.findViewById(mBaseAttribute.mTitleLayoutId)
                v?.gone()
            }
        }
    }

    //XxFragment -> fragment_xx_layout
    private fun initContentView(): Int {
        if (mBaseAttribute.mContentLayoutId != 0) {
            return mBaseAttribute.mContentLayoutId
        } else if (mBaseAttribute.mSetContentView) {
            val strClassName = this.javaClass.getName()
            val nIndex = strClassName.lastIndexOf(".")
            if (nIndex != -1) {
                val cName = strClassName.substring(nIndex + 1)
                var strResourceName = "fragment" + cName.replaceFirst("Fragment".toRegex(), "")
                strResourceName = strResourceName.camelToUnderline()
                var nLayoutId = resources.getIdentifier(
                    strResourceName,
                    "layout",
                    getBaseActivity()?.packageName
                )
                if (nLayoutId != 0) {
                    return nLayoutId
                } else {
                    strResourceName += "_layout"
                    nLayoutId = resources.getIdentifier(
                        strResourceName,
                        "layout",
                        getBaseActivity()?.packageName
                    )
                    return nLayoutId
                }
            }
        }
        return 0
    }

    open protected fun onCreateBackButton(): View? {
        return mBaseUIFactory?.createTitleBackButton()
    }

    protected fun addTextInTitle(nResId: Int) {
        mTextViewTitle = onCreateTitleTextView(nResId)
        mRelativeLayoutTitle?.addView(mTextViewTitle, onCreateTitleTextViewLayoutParams())
    }

    protected fun addTextInTitle(strText: String) {
        mTextViewTitle = onCreateTitleTextView(strText)
        mRelativeLayoutTitle?.addView(mTextViewTitle, onCreateTitleTextViewLayoutParams())
    }

    protected fun onCreateTitleTextView(nResId: Int): TextView? {
        val textView = LayoutInflater.from(activity).inflate(
            mBaseAttribute.mTitleTextLayoutId,
            null
        ) as TextView
        try {
            textView.setText(nResId)
        } catch (e: Exception) {
        }

        return textView
    }

    protected fun onCreateTitleTextView(strText: String): TextView {
        val textView = LayoutInflater.from(activity)
            .inflate(mBaseAttribute.mTitleTextLayoutId, null) as TextView
        textView.text = strText
        return textView
    }

    protected fun onCreateTitleTextViewLayoutParams(): RelativeLayout.LayoutParams {
        return RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT,
            RelativeLayout.LayoutParams.MATCH_PARENT
        )
    }

    protected fun onCreateBackButtonLayoutParams(): RelativeLayout.LayoutParams {
        val lp = RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.MATCH_PARENT
        )
        lp.leftMargin = mBaseUIFactory?.titleBackButtonLeftMargin ?: 0
        lp.topMargin = mBaseUIFactory?.titleBackButtonTopMargin ?: 0
        lp.bottomMargin = mBaseUIFactory?.titleBackButtonBottomMargin ?: 0
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
        return lp
    }

    protected fun addSubTitle(): TextView {
        mTextViewTitle?.setPadding(
            mTextViewTitle!!.getPaddingLeft(),
            mTextViewTitle!!.getPaddingTop(),
            mTextViewTitle!!.getPaddingRight(),
            15.dp2px()
        )
        val textViewSubTitle =
            LayoutInflater.from(activity).inflate(R.layout.textview_subtitle, null) as TextView
        mRelativeLayoutTitle?.addView(
            textViewSubTitle,
            RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT
            )
        )
        textViewSubTitle.setPadding(
            textViewSubTitle.paddingLeft,
            24.dp2px(),
            textViewSubTitle.paddingRight,
            textViewSubTitle.paddingBottom
        )
        mTextViewSubTitle = textViewSubTitle
        return mTextViewSubTitle!!
    }

    protected fun addImageButtonInTitleRight(resId: Int): View? {
        return if (mBaseUIFactory != null) {
            addViewInTitleRight(
                mBaseUIFactory!!.createTitleRightImageButton(resId),
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                mBaseUIFactory?.titleRightImageButtonTopMargin ?: 0,
                mBaseUIFactory?.titleRightImageButtonRightMargin ?: 0
            )
        } else null
    }

    protected fun addTextButtonInTitleRight(textId: Int): View? {
        return if (mBaseUIFactory != null) {
            addViewInTitleRight(
                mBaseUIFactory!!.createTitleRightTextButton(textId),
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.MATCH_PARENT,
                mBaseUIFactory?.titleRightTextButtonTopMargin ?: 0,
                mBaseUIFactory?.titleRightTextButtonRightMargin ?: 0
            )
        } else null
    }

    protected fun addTextButtonInTitleRight(text: String): View? {
        return if (mBaseUIFactory != null) {
            addViewInTitleRight(
                mBaseUIFactory!!.createTitleRightTextButton(text),
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.MATCH_PARENT,
                mBaseUIFactory?.titleRightTextButtonTopMargin ?: 0,
                mBaseUIFactory?.titleRightTextButtonRightMargin ?: 0
            )
        } else null
    }


    private val rightButtonList = mutableListOf<View>()
    protected fun removeAllRightButton(){
        rightButtonList.forEachIndexed { index, view ->
            run {
                mRelativeLayoutTitle?.removeView(view)
            }
        }
        rightButtonList.clear()
    }

    protected fun addViewInTitleRight(
        v: View,
        width: Int,
        height: Int,
        nTopMargin: Int,
        nRightMargin: Int
    ): View {
        val lp = RelativeLayout.LayoutParams(width, height)
        lp.topMargin = nTopMargin
        lp.rightMargin = nRightMargin
        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
        mRelativeLayoutTitle?.addView(v, lp)
        v.onClick {
            onTitleRightButtonClicked(it)
        }
        rightButtonList.add(v)
        return v
    }

    open protected fun onTitleRightButtonClicked(v: View) {

    }


    private var mBaseUIFactory: BaseUIFactory? = null
    protected lateinit var mBaseAttribute: BaseAttribute
    protected var mRelativeLayoutTitle: RelativeLayout? = null
    protected var mButtonBack: View? = null
    private var mTextViewTitle: TextView? = null
    private var mTextViewSubTitle: TextView? = null

    open protected fun onInitAttribute(ba: BaseAttribute) {
        if (getIntent()!!.hasExtra(IntentBuilder.EXTRA_HAS_TITLE)) {
            ba.mHasTitle = getIntent()!!.getBooleanExtra(IntentBuilder.EXTRA_HAS_TITLE, true)
        }
        if (getIntent()!!.hasExtra(IntentBuilder.EXTRA_ADD_BACK_BUTTON)) {
            ba.mAddBackButton =
                getIntent()!!.getBooleanExtra(IntentBuilder.EXTRA_ADD_BACK_BUTTON, false)
        }
        ba.mTitleLayoutId = R.id.viewTitle
        ba.mTitleTextLayoutId = R.layout.textview_title
    }

    protected fun initBaseUIFactory() {
        if (mBaseUIFactory == null) {
            val c = BaseUIProvider.baseUIFactoryClass
            if (c == null) {
                mBaseUIFactory = SimpleBaseUIFactory(requireActivity())
            } else {
                try {
                    val constructor = c!!.getDeclaredConstructor(Context::class.java)
                    mBaseUIFactory = constructor.newInstance(activity) as BaseUIFactory
                } catch (e: Exception) {
                    e.printStackTrace()
                    mBaseUIFactory = SimpleBaseUIFactory(requireActivity())
                }
            }
        }
    }

    protected class BaseAttribute {
        var mSetContentView = true
        var mContentLayoutId: Int = 0
        var mHasTitle = true
        var mTitleLayoutId: Int = 0
        var mTitleLayoutBgColorRes: Int = 0
        var mAddTitleText = true
        var mTitleTextLayoutId: Int = 0
        var mTitleTextStringId: Int = 0
        var mTitleText: String? = null
        var mAddBackButton = true
    }

    fun getBaseActivity(): BaseUIActivity? {
        if (activity is BaseUIActivity) {
            return activity as BaseUIActivity
        } else {
            return null
        }
    }

    open fun showProgress() {
        getBaseActivity()?.showProgress(0f)
    }

    open fun dismissProgress() {
        getBaseActivity()?.dismissProgress()
    }


    open fun onBackPressed(): Boolean {
        return true
    }


    fun startParentActivity(clazz: Class<out Fragment>, bundle: Bundle? = null) {
        val builder = IntentBuilder.Builder()
        bundle?.let {
            builder.putExtras(it)
        }
        builder.startParentActivity(activity, clazz)
    }


    fun <K, V> startParentActivity(clazz: Class<out Fragment>, vararg params: Pair<K, V>?) {
        val builder = IntentBuilder.Builder()
        params?.forEach {
            builder.putExtra(it?.first.toString(), it?.second?.toJson())
        }
        builder.startParentActivity(activity, clazz)
    }


    fun startActivity(clazz: Class<out Activity>) {
        IntentBuilder.Builder().setClass(requireContext(), clazz).startActivity()
    }

    protected var mPool: RecyclerView.RecycledViewPool? = null
    open fun setPool(pool: RecyclerView.RecycledViewPool?) {
        mPool = pool
    }

    override fun onResume() {
        super.onResume()
        ("fragment---->" + this.javaClass.simpleName).print()
    }

    open fun <T : View> findViewById(@IdRes id: Int): T? {
        return getView()?.findViewById(id)
    }

}